package controllers

import (
	"alarmservice/com"
	"alarmservice/model"
	"alarmservice/service"
	"alarmservice/tracingservice"
	"sort"
	"strconv"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
)

//Login处理
type TracingController struct {
	ProjectController
	Tracing *model.Tracing
}

func (c *TracingController) NextPrepare() {
	c.NeedLogin = true

	tracingId := c.Ctx.Input.Param(":tid")

	//初始化
	c.ProjectController.NextPrepare()

	//不是跟随者不能访问
	if !c.IsFollower() {
		c.Abort("403")
		return
	}

	if tracingId != "" {
		tracingIdInt64, err := strconv.ParseInt(tracingId, 10, 64)
		if err == nil {
			c.initTracing(tracingIdInt64)
		}
	}

	if c.Project == nil {
		c.Abort("404")
		return
	}

	//将项目相关的面包屑导航加载好
	c.AddProjectBreadCrumb()
	tracingListUrl := "/project/" + strconv.FormatInt(c.Project.Id, 10) + "/tracing?listsubmenu=" + c.Data["SubMenu"].(string)
	c.AddBreadCrumb("监控列表", tracingListUrl)
}

func (c *TracingController) initTracing(id int64) bool {
	tracing := &model.Tracing{}
	err := model.GetById(id, tracing)

	if err == nil {
		c.Tracing = tracing
		c.Data["Tracing"] = tracing
		return true
	} else {
		return false
	}
}

func (c *TracingController) PageCreate() {
	c.Data["IsEdit"] = false
	//创建监控点
	if c.Ctx.Request.Method == "GET" {
		c.createGet()
	} else {
		c.createPost()
	}
}

func (c *TracingController) createGet() {
	postTracingMap, ok := c.Data["PostTracingMap"]
	if !ok {
		if c.Ctx.Request.Method == "POST" {
			c.Data["PostTracingMap"] = c.Data["POST"]
		} else {
			c.Data["PostTracingMap"] = make(map[string]interface{})
		}
	} else {
		c.Data["PostTracingMap"] = postTracingMap
	}

	c.TplName = "tracing/edit.tpl"
}

func (c *TracingController) createPost() {
	valid := validation.Validation{}

	postTracing := model.NewTracing()

	if err := c.ParseForm(postTracing); err != nil {
		c.Data["Errors"] = err.Error()
		c.createGet()
		return
	}

	postTracingMap := model.Obj2Map(*postTracing)

	c.Data["PostTracingMap"] = postTracingMap

	b, err := valid.Valid(postTracing)

	if err != nil {
		c.Abort("500")
	}

	valid.Required(postTracing.Key, "Key.Required")
	valid.MaxSize(postTracing.Key, 50, "Key.Max")
	valid.Alpha(postTracing.Key, "Key.Alpha")

	//根据监控点类型进行特殊检查
	ok, err := tracingservice.CheckPostTracingDataByType(postTracing)
	if !ok {
		valid.SetError("TracingTime", err.Error())
		//出现错误b强制为false
		b = false
	}

	if !b {
		mapFormErrs := com.ValidErrorToMapByField(valid.Errors)

		c.SetFormErrsToJson(mapFormErrs)
		c.createGet()
		return
	}

	postTracing.UserId = c.AdminUser.Id
	postTracing.ProjectId = c.Project.Id

	err = model.Insert(postTracing)
	if err != nil {
		c.Abort("500")
		return
	}

	itracing, _ := tracingservice.NewITracing(postTracing)
	//创建也应该处理
	itracing.DoEnabled()

	//成功跳转
	c.Redirect("/project/"+strconv.FormatInt(c.Project.Id, 10)+"/tracing/"+strconv.FormatInt(postTracing.Id, 10)+"/update", 302)
	return
}

func (c *TracingController) PageUpdate() {
	c.Data["IsEdit"] = true

	if c.Tracing == nil || c.Tracing.Id <= 0 {
		c.Abort("404")
		return
	}

	if c.Ctx.Request.Method == "GET" {
		c.updateGet()
	} else {
		c.updatePost()
	}
}

func (c *TracingController) updateGet() {
	_, ok := c.Data["PostTracingMap"]
	if !ok {
		c.Data["PostTracingMap"] = model.Obj2Map(*c.Tracing)
	}

	//都是显示内容而已
	c.createGet()
	return
}

func (c *TracingController) updatePost() {
	valid := validation.Validation{}

	postTracing := &model.Tracing{}

	if err := c.ParseForm(postTracing); err != nil {
		c.Data["Errors"] = err.Error()
		c.createGet()
		return
	}

	postTracingMap := model.Obj2Map(*postTracing)

	c.Data["PostTracingMap"] = postTracingMap

	b, err := valid.Valid(postTracing)

	if err != nil {
		c.Abort("500")
	}

	//根据监控点类型进行特殊检查
	ok, err := tracingservice.CheckPostTracingDataByType(postTracing)
	if !ok {
		valid.SetError("TracingTime", err.Error())
		//出现错误b强制为false
		b = false
	}

	if !b {
		mapFormErrs := com.ValidErrorToMapByField(valid.Errors)

		c.SetFormErrsToJson(mapFormErrs)
		c.updateGet()
		return
	}

	//不允许修改key
	postTracing.Key = ""

	//应该检查tracing_time是否有问题

	err = model.UpdateById(c.Tracing.Id, postTracing)
	if err != nil {
		c.Abort("500")
		return
	}

	//前台没有传状态信息
	postTracing.Status = c.Tracing.Status

	if postTracing.Status == model.TracingStatusEnabled {
		postTracing.Id = c.Tracing.Id
		postTracing.Key = c.Tracing.Key
		postTracing.ProjectId = c.Tracing.ProjectId
		postTracing.UserId = c.Tracing.UserId

		itracing, _ := tracingservice.NewITracing(postTracing)
		//值被修改了，如果status是打开的，应该更新
		itracing.DoEnabled()
	}

	//成功跳转
	c.Redirect("/project/"+strconv.FormatInt(c.Project.Id, 10)+"/tracing/"+strconv.FormatInt(c.Tracing.Id, 10)+"/update?listsubmenu="+c.Data["SubMenu"].(string), 302)
	return
}

//报警记录
func (c *TracingController) PageList() {
	total, err := model.Orm.Where("project_id=? and status!=?", c.Project.Id, model.StatusDeleted).Count(&model.Tracing{})
	if err != nil {
		c.Abort("500")
		return
	}
	//设置分页
	paginator := c.SetPaginator(20, total)

	tracings := make(model.MapTracing)

	err = model.Orm.Where("project_id=? and status!=?", c.Project.Id, model.StatusDeleted).Limit(paginator.PerPageNums, paginator.Offset()).OrderBy("create_time desc").Find(&tracings)
	if err != nil {
		beego.Error(err)
		c.Abort("500")
		return
	}

	tracingIds := tracings.GetTracingIds()
	sort.Sort(sort.Reverse(model.IdList(tracingIds)))
	c.Data["Tracings"] = tracings
	c.Data["TracingIds"] = tracingIds

	users, err := model.GetUserFromUserIdContainer(tracings)
	if err != nil {
		beego.Error(err)
		c.Abort("500")
		return
	}
	c.Data["Users"] = users

	projects, err := model.GetProjectFromProjectIdContainer(tracings)
	if err != nil {
		c.Abort("500")
		return
	}
	c.Data["Projects"] = projects

	//获取监控点最后报警时间
	lastTracingWarningTimes, err := service.GetTracingLastWarningTimeByTracingIds(tracingIds)
	if err != nil {
		c.Abort("500")
		return
	}

	c.Data["LastTracingWarningTimes"] = lastTracingWarningTimes

	c.TplName = "tracing/list.tpl"
}

func (c *TracingController) PageWarningList() {
	if c.Tracing == nil || c.Tracing.Id <= 0 {
		c.Abort("404")
		return
	}
	tracingBaseUrl := "/project/" + strconv.FormatInt(c.Project.Id, 10) + "/tracing/" + strconv.FormatInt(c.Tracing.Id, 10)
	tracingUrl := tracingBaseUrl + "/update?listsubmenu=" + c.Data["SubMenu"].(string)
	warningListUrl := tracingBaseUrl + "/warnings?listsubmenu=" + c.Data["SubMenu"].(string)
	c.AddBreadCrumb(c.Tracing.Title, tracingUrl)
	c.AddBreadCrumb("报警信息", warningListUrl)

	total, err := model.CountByExample(&model.Warning{TracingId: c.Tracing.Id})

	if err != nil {
		beego.Error(err)
		c.Abort("500")
		return
	}

	paginator := c.SetPaginator(20, total)
	warnings := make(model.MapWarning)
	err = model.Orm.Where("tracing_id=?", c.Tracing.Id).OrderBy("create_time desc").Limit(paginator.PerPageNums, paginator.Offset()).Find(&warnings)
	if err != nil {
		beego.Error(err)
		c.Abort("500")
		return
	}

	warningIds := warnings.GetWarningIds()
	sort.Sort(sort.Reverse(model.IdList(warningIds)))
	c.Data["Warnings"] = warnings
	c.Data["WarningIds"] = warningIds

	//获取项目相关数据
	projects, err := model.GetProjectFromProjectIdContainer(warnings)
	if err != nil {
		c.Abort("500")
		return
	}
	c.Data["Projects"] = projects

	tracings, err := model.GetTracingFromTracingIdContainer(warnings)
	if err != nil {
		c.Abort("500")
		return
	}
	c.Data["Tracings"] = tracings

	c.TplName = "tracing/warnings.tpl"
}

func (c *TracingController) PageAjaxSetStatus() {
	status, err := c.GetInt("status", 0)
	if err != nil || status == 0 {
		c.returnJson(com.ApiUnknowFailed("need params"))
		return
	}

	if status != model.TracingStatusEnabled && status != model.TracingStatusDisabled {
		c.returnJson(com.ApiUnknowFailed("params error!"))
		return
	}

	err = model.UpdateById(c.Tracing.Id, model.Tracing{Status: status})
	if err != nil {
		c.returnJson(com.ApiUnknowFailed("system error!"))
		return
	}

	itracing, _ := tracingservice.NewITracing(c.Tracing)
	if status == model.TracingStatusEnabled {
		err := itracing.DoEnabled()
		if err != nil {
			c.returnJson(com.ApiUnknowFailed(err.Error()))
			return
		}
	} else {
		err := itracing.DoDisabled()
		if err != nil {
			c.returnJson(com.ApiUnknowFailed(err.Error()))
			return
		}
	}

	c.returnJson(com.ApiSucc(""))
	return
}

func (c *TracingController) PageAjaxDelTracing() {
	tracingId, err := c.GetInt64("id", 0)
	if err != nil {
		c.returnJson(com.ApiUnknowFailed("no params"))
		return
	}

	tracing := &model.Tracing{}
	err = model.GetById(tracingId, tracing)
	if err != nil {
		c.returnJson(com.ApiUnknowFailed("get tracing error"))
		return
	}

	itracing, _ := tracingservice.NewITracing(tracing)
	//删除也应该处理
	err = itracing.DoDeleted()
	if err != nil {
		c.returnJson(com.ApiUnknowFailed(err.Error()))
		return
	}

	err = model.DeleteByExample(model.Tracing{Id: tracingId})
	if err != nil {
		c.returnJson(com.ApiUnknowFailed("system error!"))
		return
	}

	//注意: 不删除warning记录，防止恶意删除清空报警记录

	c.returnJson(com.ApiSucc(""))
	return
}
